package pl.edu.agh.pros.proxy.handler;

import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;

import org.ros.node.ConnectedNode;
import org.ros.node.DefaultNodeMainExecutor;
import org.ros.node.Node;
import org.ros.node.NodeConfiguration;
import org.ros.node.NodeListener;
import org.ros.node.NodeMainExecutor;

import pl.edu.agh.pros.internal.proxy.AbstractProxyNode;
import pl.edu.agh.pros.proxy.RosProxyHandler;

public abstract class AbstractProxyHandler implements RosProxyHandler, NodeListener {

	private static final String NODE_PREFIX = "proxyNode"; //$NON-NLS-1$

	protected static final NodeMainExecutor nodeRunner = DefaultNodeMainExecutor.newDefault();
	protected final AbstractProxyNode proxyNode;
	protected final NodeConfiguration nodeConfiguration;
	protected boolean started = false;
	private CountDownLatch latch = new CountDownLatch(1);

	public AbstractProxyHandler(AbstractProxyNode proxyNode, NodeConfiguration nodeConfiguration) {
		this.proxyNode = proxyNode;
		this.nodeConfiguration = nodeConfiguration;
	}

	@SuppressWarnings("serial")
	@Override
	public void start() {
		nodeRunner.execute(proxyNode, nodeConfiguration.setNodeName(generateNodeName()), new ArrayList<NodeListener>() {
			{
				add(AbstractProxyHandler.this);
			};
		});
	}

	@Override
	public void stop() {
		nodeRunner.shutdownNodeMain(proxyNode);
		nodeRunner.shutdown();
		proxyNode.dispose();
	}

	@Override
	public void awaitStart() {
		if (started) {
			return;
		}
		try {
			latch.await();
		} catch (InterruptedException e) {
			// ignore
		}
	}

	/**
	 * NodeListener methods
	 */

	@Override
	public void onStart(ConnectedNode node) {
		started = true;
		latch.countDown();
	}

	@Override
	public void onError(Node arg0, Throwable arg1) {
		// ignore
	}

	@Override
	public void onShutdown(Node arg0) {
		// ignore
	}

	@Override
	public void onShutdownComplete(Node arg0) {
		// ignore
	}

	private String generateNodeName() {
		return NODE_PREFIX + System.currentTimeMillis() + Thread.currentThread().getId();
	}
}
